%option yylineno
%{
#include "lexical.h"
#include "syntax.tab.h"
void lexPrint(const char *format, ...){
#ifdef LOCAL
	fprintf(stderr, "syntaxPrint: Line %d:\n\t", yylloc.first_line);
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
	fprintf(stderr, "\n");
#endif
}
void lex_error(char *msg);
int lexError=0;
int yycolumn = 1;

#define YY_USER_ACTION \
	yylloc.first_line = yylloc.last_line = yylineno; \
	yylloc.first_column = yycolumn; \
	yylloc.last_column = yycolumn + yyleng - 1; \
	yycolumn += yyleng;
%}

DIGIT [0-9]
DIGITS {DIGIT}+
letter [a-zA-Z_]
SIGN [+-]
DOT \.
WHITESPACE [ \t\r\n]+
ID [a-zA-Z_][a-zA-Z0-9_]*
IDERROR {DIGITS}{letter}+[a-zA-Z0-9_]+
DEC 0|([1-9][0-9]*)
FLOAT_E ({DOT}{DIGITS}|{DIGITS}{DOT}|{DIGITS}{DOT}{DIGITS}|{DIGITS})([eE]{SIGN}?{DIGITS})
FLOAT {DIGITS}\.{DIGITS}
SEMI ";"
COMMA ","
ASSIGN "="
RELOP ">"|"<"|">="|"<="|"=="|"!="
PLUS "+"
MINUS "-"
MUL "*"
DIV  "/"
AND "&&"
OR "||"
NOT "!"
TYPE "int"|"float"
LP "("
RP ")"
LB "["
RB "]"
LC "{"
RC "}"
STRUCT "struct"
RETURN "return"
IF "if"
ELSE "else"
WHILE "while"
%%
\n {yycolumn = 1;}
{WHITESPACE} {/* 忽略空白字符 */}
{IDERROR}	{
	lexPrint("IDERROR");
	lex_error("Invalid identifier");
	return ID;
}
{DEC} {
	lexPrint("DEC");
	return INT;
}
{FLOAT_E} {
	lexPrint("FLOAT_E");
	return FLOAT;
}
{FLOAT} {
	lexPrint("FLOAT");
	return FLOAT;
}
{TYPE} {
	lexPrint("TYPE");
	return TYPE;
}
{STRUCT} {
	return STRUCT;
}
{RETURN} {
	return RETURN;
}
{IF} {
	return IF;
}
{ELSE} {
	return ELSE;
}
{WHILE} {
	return WHILE;
}
{SEMI} {
	return SEMI;
}
{COMMA} {
	return COMMA;
}
{ASSIGN} {
	return ASSIGN;
}
{RELOP} {
	return RELOP;
}
{PLUS}	{
	lexPrint("PLUS");
	return PLUS;
}
{MINUS}	{
	lexPrint("MINUS");
	return MINUS;
}
{MUL}	{
	lexPrint("MUL");
	return MUL;
}
{DIV}	{
	lexPrint("DIV");
	return DIV;
}
{AND} {
	return AND;
}
{OR} {
	return OR;
}
{NOT} {
	return NOT;
}
{ID}	{
	lexPrint("ID");
	return ID;
}
{DOT} {
	return DOT;
}
{LP} {
	return LP;
}
{RP} {
	return RP;
}
{LB} {
	return LB;
}
{RB} {
	return RB;
}
{LC} {
	return LC;
}
{RC} {
	return RC;
}
.  {printf("Error type A at Line %d: unmatched string.\n", yylineno);}

%%

void lex_error(char *msg){
	lexError += 1;
	printf("Error type A at Line %d: %s\n", yylineno, msg);
}